from rest_framework_jwt.views import ObtainJSONWebToken
from luffycityapi.utils.tencentcloudapi import TencentCloudAPI, TencentCloudSDKException
from rest_framework.response import Response
from rest_framework import status
from rest_framework.views import APIView
from .models import User
from rest_framework.generics import CreateAPIView
from .serializers import UserRegisterModelSerializer
from django_redis import get_redis_connection
from ronglianyunapi import settings
import random
from .tasks import send_sms


class LoginAPIView(ObtainJSONWebToken):
    """用户登录视图"""

    def post(self, request, *args, **kwargs):
        # 校验用户操作验证码成功以后的ticket临时票据
        try:
            """
               # 登录之前调用滑块验证，通过后在走父类的序列化校验
            api = TencentCloudAPI()  # 实例化api对象
            #
            result = api.captcha(
                request.data.get("ticket"),
                request.data.get("randstr"),
                # request._request.META.get("REMOTE_ADDR"),
                request.META.get("REMOTE_ADDR"),
            )
            if result:
                # 验证通过
                print('验证通过')
            """
            # 登录实现代码，调用父类实现的登录视图方法
            return super().post(request, *args, **kwargs)
            # else:
            #     # 如果返回值不是True，则表示验证失败
            #     raise TencentCloudSDKException
        except TencentCloudSDKException as err:
            return Response({"errmsg": "验证码校验失败！"}, status=status.HTTP_400_BAD_REQUEST)


class MobileAPIView(APIView):
    def get(self, request, mobile):
        """
        校验手机号是否已注册
        :param request:
        :param mobile: 手机号
        :return:
        """
        try:
            # 如果符合筛选条件的对象超过一个或者没有都会抛出错误
            User.objects.get(mobile=mobile)
            return Response({"errmsg": "当前手机号已注册"}, status=status.HTTP_400_BAD_REQUEST)
        except User.DoesNotExist:
            # 如果查不到该手机号的注册记录，则证明手机号可以注册使用
            return Response({"errmsg": "OK"}, status=status.HTTP_200_OK)


class UserAPIView(CreateAPIView):
    """用户注册视图"""
    queryset = User.objects.all()
    serializer_class = UserRegisterModelSerializer


class SMSAPIView(APIView):
    """SMS短信接口视图"""

    def get(self, request, mobile):
        """发送短信验证码"""

        redis = get_redis_connection("sms_code")  # 获取redis连接对象
        # print(redis)
        # 判断手机短信是否处于发送冷却中[60秒只能发送一条]
        interval = redis.ttl(f"interval_{mobile}")  # 通过ttl方法可以获取保存在redis中的变量的剩余有效期
        # print('interval>>>>>>>>>>>>', interval, type(interval))
        if interval != -2:  # -2 表示当前数据已经过期或不存在
            return Response(
                {"errmsg": f"短信发送过于频繁，请{interval}秒后再次点击获取!"},
                status=status.HTTP_400_BAD_REQUEST
            )
        # 基于随机数生成短信验证码
        # code = "%06d" % random.randint(0, 999999)
        code = f"{random.randint(0, 999999):06d}"  # 生成6位数随机验证码
        # print("code:>>>>>>>",code)
        # 获取短信有效期的时间
        time = settings.RONGLIANYUN.get("sms_expire")  # time:300s 短信有效期
        # 短信发送间隔时间
        sms_interval = settings.RONGLIANYUN["sms_interval"]  # 短信发送间隔时间 60s

        # 调用第三方sdk发送短信
        # send_sms(settings.RONGLIANYUN.get('reg_tid'), mobile, datas=(code, time // 60))

        # 异步发送短信
        send_sms.delay(settings.RONGLIANYUN.get('reg_tid'), mobile, datas=(code, time // 60))

        # 记录code到redis中，并以time作为有效期
        # 使用redis提供的管道对象pipeline来优化redis的写入操作[添加/修改/删除]
        pipe = redis.pipeline()
        pipe.multi()  # 开启事务
        # 设置验证码超时时间 300s
        pipe.setex(f"sms_{mobile}", time, code)  # setex(name, value, time) 设置值，参数：time，过期时间（数字秒 或 timedelta对象）
        pipe.setex(f"interval_{mobile}", sms_interval, "_")  # 60s有效期
        pipe.execute()  # 提交事务，同时把暂存在pipeline的数据一次性提交给redis

        return Response({"errmsg": "OK"}, status=status.HTTP_200_OK)
